package com.denghq.projectbuilder.component.swagger.autoconfigure;

import com.github.xiaoymin.swaggerbootstrapui.annotations.EnableSwaggerBootstrapUI;
import io.swagger.annotations.ApiOperation;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.ApiKey;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import javax.servlet.DispatcherType;
import java.util.List;

import static com.google.common.collect.Lists.newArrayList;

@Configuration
@EnableSwagger2
@EnableSwaggerBootstrapUI
@EnableConfigurationProperties({SwaggerProperties.class})
public class SwaggerAutoConfiguration implements WebMvcConfigurer {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler(new String[]{"doc.html"}).addResourceLocations(new String[]{"classpath:/META-INF/resources/"});
        //registry.addResourceHandler("swagger-ui.html").addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("/webjars/**").addResourceLocations("classpath:/META-INF/resources/webjars/");
        registry.addResourceHandler("/swagger/**").addResourceLocations("classpath:/static/swagger/");
    }

    //兼容老版本地址 ：swagger-ui
    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        registry.addViewController("/swagger-ui.html").setViewName("forward:/doc.html");
    }

    @Bean
    public Docket createRestApi(SwaggerProperties properties) {
        return new Docket(DocumentationType.SWAGGER_2)
                .host(properties.getHost())
                .apiInfo(apiInfo(properties)).select()
                .apis(RequestHandlerSelectors.withMethodAnnotation(ApiOperation.class))
                .paths(PathSelectors.any())
                .build()
                .securitySchemes(security())
               /* .alternateTypeRules( //自定义规则，如果遇到DeferredResult，则把泛型类转成json

                        newRule(
                                typeResolver.resolve(ResultInfo.class, WildcardType.class),
                                typeResolver.resolve(typeResolver.resolve(WildcardType.class))
                        ),

                        newRule(
                                typeResolver.resolve(ResultInfo.class, typeResolver.resolve(Map.class, String.class, WildcardType.class)),
                                typeResolver.resolve(typeResolver.resolve(Map.class, String.class, typeResolver.resolve(WildcardType.class)))
                        )
                )*/;
        //.pathMapping("/");

    }

    @Bean
    public FilterRegistrationBean<SwaggerCrosFilter> swaggerCrosFilterRegistration() {
        FilterRegistrationBean<SwaggerCrosFilter> registration = new FilterRegistrationBean<>();
        registration.setDispatcherTypes(DispatcherType.REQUEST);
        registration.setFilter(new SwaggerCrosFilter());
        registration.addUrlPatterns("/v2/api-docs");
        registration.setName("SwaggerCrossFilter");
        registration.setOrder(Integer.MAX_VALUE);
        return registration;
    }

    private ApiInfo apiInfo(SwaggerProperties properties) {
        return new ApiInfoBuilder()
                .title(properties.getTitle())
                .description(properties.getDescription())
                .termsOfServiceUrl(properties.getTermsOfServiceUrl())
                .version(properties.getVersion())
                .build();
    }

    private List<ApiKey> security() {
        return newArrayList(
                new ApiKey("Authorization", "Authorization", "header")
        );
    }

}